﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace SmartCard.Framework.ApiPlugins.FileSystem
{
	public class FileSystemReader : ISmartCardReader, IDisposable
	{
		#region fields

		private const string __FileExtension = @"sc.frmk";
		private readonly string __InsertedCardFileName;

		/// <summary>
		/// used to determine if a card has been inserted
		/// </summary>
		private FileSystemWatcher _watcher;

		#endregion

		#region events

		public event EventHandler<CardInsertedEventArgs> CardInserted = delegate { };
		public event EventHandler<CardRemovedEventArgs> CardRemoved = delegate { };
		public event EventHandler<ReaderErrorEventArgs> ReaderError = delegate { };

		#endregion

		#region properties

		/// <summary>
		/// Get the friendly name for the reader
		/// </summary>
		public string FriendlyName
		{ get; private set; }

		/// <summary>
		/// Get the reader type
		/// </summary>
		public eReaderType ReaderType
		{ get; private set; }

		#endregion

		#region construction
		
		public FileSystemReader(string readerName, eReaderType readerType)
		{
			FriendlyName = readerName;
			ReaderType = readerType;

			__InsertedCardFileName = string.Format(@"InsertedCard_{0}{1}",
				readerName, __FileExtension);

			InitWatcher();
		}

		#endregion

		#region public methods

		public ICard GetInsertedCard()
		{
			return null;
		}

		public bool ContainsCard()
		{
			return File.Exists(__InsertedCardFileName);
		}

		/// <summary>
		/// Mock the insertion of a card into this reader. 
		/// </summary>
		public void InsertCard()
		{
			if (!File.Exists(__InsertedCardFileName))
			{
				// make sure we close the file, otherwise we are at
				// this disposal of the GC
				var fs = File.Create(__InsertedCardFileName);
				if (fs != null)
				{ fs.Dispose(); }
			}
		}

		/// <summary>
		/// Remove card from the reader
		/// </summary>
		public void RemoveCard()
		{
			File.Delete(__InsertedCardFileName);
		}

		#endregion

		#region privates

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
		private void InitWatcher()
		{
			_watcher = new FileSystemWatcher(
				Directory.GetCurrentDirectory(), __InsertedCardFileName);

			_watcher.Created += _watcher_Created;
			_watcher.Renamed += _watcher_Renamed;
			_watcher.Deleted += _watcher_Deleted;

			_watcher.EnableRaisingEvents = true;
		}

		private void _watcher_Deleted(object sender, FileSystemEventArgs e)
		{
			if (e.Name == __InsertedCardFileName)
			{
				CardRemoved(this, null);
			}
		}

		private void _watcher_Renamed(object sender, RenamedEventArgs e)
		{
			if (e.Name == __InsertedCardFileName)
			{
				CardInserted(this, null);
			}
			else if (e.OldName == __InsertedCardFileName)
			{
				CardRemoved(this, null);
			}
		}

		private void _watcher_Created(object sender, FileSystemEventArgs e)
		{
			if (e.Name == __InsertedCardFileName)
			{
				CardInserted(this, null);
			}
		}

		#endregion

		#region dispose pattern

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (_watcher != null)
				{
					_watcher.Dispose();
					_watcher = null;
				}
			}
		}

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		#endregion
	}
}
